unit tilesetgraphicsunit;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Graphics, fpjson, BGRABitmapTypes,
  BGRABitmap;

type

  TTilesetGraphicsSetType = (
    tgstA1 := 0,
    tgstA2 := 1,
    tgstA3 := 2,
    tgstA4 := 3,
    tgstA5 := 4,
    tgstB := 5,
    tgstC := 6,
    tgstD := 7,
    tgstE := 8
  );

  { TTilesetGraphics }

  TTilesetGraphics = class
    private
      TilesetNames: array [0..8] of String;
      procedure DestroyImages;
    public
      Bitmaps: array [0..8] of TBGRABitmap;
      procedure SetTileset(ATileset: TJSONObject);
      function HasSet(SetType: TTilesetGraphicsSetType): Boolean; overload;
      function HasSet(Index: Integer): Boolean; overload;
      function GetUpperTile(TileId: Integer): TBitmap;
      destructor Destroy; override;
  end;

implementation

uses
  globals, Dialogs;

procedure TTilesetGraphics.SetTileset(ATileset: TJSONObject);
var
  I: Integer;
  Filename: String;
  NewNames: TJSONArray;
begin
  if ATileset = nil then begin
    DestroyImages;
    Exit;
  end;

  NewNames := ATileset.Arrays['tilesetNames'];

  for I := Low(Bitmaps) to High(Bitmaps) do
    if NewNames.Strings[I] <> TilesetNames[I] then begin
      TilesetNames[I] := NewNames.Strings[I];

      if Bitmaps[I] <> nil then begin
        Bitmaps[I].Free;
        Bitmaps[I] := nil;
      end;

      Filename := Game.GetImageFilename(TilesetNames[I], 'tilesets');
      if FileExists(Filename) then
        try
          Bitmaps[I] := TBGRABitmap.Create(Filename, True);
          Bitmaps[I].CanvasBGRA.AntialiasingMode := amOff;
        except
          Bitmaps[I].Free;
          Bitmaps[I] := nil;
        end;
    end;
end;

procedure TTilesetGraphics.DestroyImages;
var
  I: Integer;
begin
  for I := Low(Bitmaps) to High(Bitmaps) do begin
    TilesetNames[I] := '';
    if Bitmaps[I] <> nil then
      Bitmaps[I].Free;
    Bitmaps[I] := nil;
  end;
end;

function TTilesetGraphics.HasSet(SetType: TTilesetGraphicsSetType): Boolean;
begin
  HasSet := HasSet(Integer(SetType));
end;

function TTilesetGraphics.HasSet(Index: Integer): Boolean;
begin
  HasSet := (Index >= Low(Bitmaps)) and (Index <= High(Bitmaps))
                                              and (Bitmaps[Index] <> nil);
end;

function TTilesetGraphics.GetUpperTile(TileId: Integer): TBitmap;
var
  TileInSetId, SetId: Integer;

  procedure FindTileInSet;
  begin
    SetId := 5 + (TileId div 256);
    TileInSetId := TileId mod 256;
  end;

var
  CroppedGfx: TBitmap;
  CellWidth, CellHeight: Integer;

  Column, Row, PosInRow, X, Y: Integer;
  Src, Dst: TRect;
begin
  CellWidth := 48; //TODO: adapt to other cell widths
  CellHeight := 48; //TODO: adapt to other cell heights

  FindTileInSet;
  if not HasSet(SetId) then
    Exit(nil);

    CroppedGfx := TBitmap.Create;
    CroppedGfx.SetSize(CellWidth, CellHeight);

    Column := (TileInSetId div 8) div 16;
    Row := (TileInSetId div 8) mod 16;
    PosInRow := TileInSetId mod 8;

    X := ((Column * 8) + PosInRow);
    Y := Row;

    CroppedGfx.Canvas.Brush.Color := clBtnFace;
    CroppedGfx.Canvas.FillRect(0,0, CellWidth, CellHeight);

    //CroppedGfx.Canvas.TextOut(0, 0, IntToStr(TileId));

    Dst := Rect(0, 0, CellWidth, CellHeight);

    Src := Rect(X * CellWidth,      Y * CellHeight,
                (X+1) * CellWidth, (Y+1) * CellHeight);
    CroppedGfx.Canvas.CopyRect(Dst, Bitmaps[SetId].Canvas, Src);

    GetUpperTile := CroppedGfx;
end;

destructor TTilesetGraphics.Destroy;
begin
  DestroyImages;
  inherited
end;

end.

